home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
500 MB Nyheder Direkte fra Internet 2
/
500 MB nyheder direkte fra internet CD 2.iso
/
start
/
data
/
text
/
style.txt
< prev
next >
Wrap
Text File
|
1994-09-21
|
36KB
|
794 lines
INVENTING A PROGRAM
First, decide on your ultimate goal. Be optimistic. Maybe you'd
like the computer to play the perfect game of chess? Or translate
every English sentence into French?
Research the past
Chances are, whatever you want the computer to do, someone else
has thought of the same idea already, and written a program for
it.
Find out. Ask your friends. Ask the people in nearby schools,
computer stores, computer centers, companies, libraries, and
bookstores. Look through books and magazines. There are even
books that list what programs have been written. Ask the company
you bought your computer from.
Even if you don't find exactly the program you're looking for,
you may find one that's close enough to be okay, or that will
work with just a little fixing, or can serve as part of your
program, or will at least give you a clue as to where to begin.
In one of the textbooks or magazines, you'll probably find a
discussion of the problem you're trying to solve, and the pros
and cons of various solutions to it ___ some methods are faster
than others.
Remember: if you keep your head in the sand, and don't look at
what other people have done already, your programming effort may
turn out to be a mere exercise useless to the rest of the world.
Simplify
All too often, programmers embark on huge projects and never
get them done. Once you have an idea of what's been done before,
and how hard your project seems to be, simplify it. Instead of
making the computer play a perfect game of chess, how about
settling for a game in which the computer plays unremarkably but
at least doesn't cheat? Instead of translating every English
sentence into French, how about translating just English colors?
(We wrote that program already.) In other words, pick a less
ambitious, more realistic goal, which if you achieve it, will
make you feel good and will be a steppingstone to your ultimate
goal.
Finding a bug in a program is like finding a needle in a
haystack: removing the needle is easier if the haystack is small
than if you wait until more hay's been piled on.
Specify the I/O
Make your new, simple goal more precise. That's called
specification. One way to be specific is to draw a picture,
showing what your screen will look like if your program's running
successfully.
In that picture, find the lines typed by the computer. They
become the PRINT statements in your program. Find the lines typed
by the human: they become the INPUT statements. Now you can start
writing your program: write the PRINT and INPUT statements on
paper, with a pencil, and leave blank lines between them. You'll
fill in the blanks later.
Suppose you want the
computer to find the average of two numbers. Your picture will
look like this:
RUN
WHAT'S THE FIRST NUMBER? number
WHAT'S THE SECOND NUMBER? number
THE AVERAGE IS number
Your program at this stage will be:
10 INPUT "WHAT'S THE FIRST NUMBER";A
20 INPUT "WHAT'S THE SECOND NUMBER";B
etc.
100 PRINT "THE AVERAGE IS";C
All you have left to do is figure out what the ``etc.'' is.
Here's the general method. . . .
Choose your statements
Suppose you didn't have
a computer. Then how would you get the answer?
Would you have to use a
mathematical formula? If so, put the formula into your program,
but remember that the left side of the equation must have just
one variable. For example, if you're trying to solve a problem
about right triangles, you might have to use the Pythagorean
formula A2+B2=C2; but the left side of the equation must have
just one variable, so your program must say A=SQR(C^2-B^2), or
B=SQR(C^2-A^2), or C=SQR(A^2+B^2), depending on whether you're
trying to compute A, B, or C.
Would you have to use a
memorized list, such as an English-French dictionary or the
population of each state or the weight of each chemical element?
If so, that list becomes your DATA, and you need to READ it. If
it would be helpful to have the data numbered, so the first piece
of data is called X(1), the next piece of data is called X(2),
etc., use the DIM statement.
Subscripts are
particularly useful if one long list of information will be
referred to several times in the program.
Does your reasoning
repeat? That means your program should have a loop. If you know
how many times to repeat, say FOR . . . NEXT. If you're not sure
how often, say GO TO. If the thing that's to be repeated isn't
repeated immediately, but only after several other things have
happened, call the repeated part a subroutine, put it at the end
of your program (followed by RETURN), and say GOSUB whenever you
want it done.
At some point in your
reasoning, do you have to make a decision? Do you have to choose
among several alternatives? The way to say ``choose'' is: IF . .
. THEN. If you want the computer to make the choice arbitrarily,
``by chance'', rather than because of a reason, say: IF RND(2)=1
THEN.
Do you have to compare
two things? The way to say ``compare A with B'' is: IF A=B THEN.
Write pseudocode
Some English teachers say that before you write a paper, you
should make an outline. Some computer teachers give similar
advice about writing programs.
The ``outline'' can look like a program in which some of the
lines are written in plain English instead of computerese. For
example, one statement in your outline might be:
130 A = the average of the twelve values of X
Such a statement, written in English instead of in computerese,
is called pseudocode. Later, when you fill in the details, expand
that pseudocode into the following:
130 S=O
131 FOR I = 1 TO 12
132 S=S+X(I)
133 NEXT
134 A=S/12
Organize yourself
Keep the program's over-all organization simple. That will make
it easier for you to expand it and find bugs. Here is some
folklore, handed down from generation to generation of
programmers, that will simplify your organization. . . .
Use top-down programming. That means write a one-sentence
description of your program; then expand that sentence to several
sentences; then expand each of those sentences to several more
sentences; and so on, until you can't expand any more. Then turn
each of thse new sentences into lines of program. Your program
will then be in the same order as the English sentences, and
therefore organized the same way as an English-speaking mind.
A variation is to use subroutines. That means writing the
essence of the program as a very short main routine; instead of
filling in the grubby details immediately, replace each piece of
grubbiness by the word GOSUB. After the main routine is written,
write each subroutine. Your program will be like a good book:
your main routine will move swiftly, and the annoying details
will be relegated to the appendices at the back; the appendices
are called subroutines. Keep each subroutine down to 50 lines; if
it starts getting longer and grubbier, replace each piece of
grubbiness by a GOSUB to another subroutine, written afterwards
and having higher line numbers.
Avoid GO TO. It's hard for a human to understand a program
that's a morass of GO TO statements. It's like trying to read a
book where each paragraph says to turn to a different page! When
you must say GO TO, try to go forward instead of backwards, and
not go too far.
Divide your program into modules. A module is a bunch of
consecutive lines forming a unit that cannot be ``punctured''; in
other words, there is no GO-TO-type statement outside the module
that sends the computer to the module's middle; the only way the
module can be activated is by starting with its top line. (If the
module's particularly nice, the only way it can be deactivated is
by arriving at its bottom line; in other words, there is no
GO-TO-type statement in the module's middle that sends the
computer outside the module.) If you used top-down programming,
each module probably corresponds to one sentence in your
program's description. Write that sentence at the top of the
module, and put an apostrophe to the left of it.
Use variables
After you've written a
few lines of your program, you may find that your reasoning
``almost repeats''; several lines bear a strong resemblance to
each other. You can't use GO TO or FOR . . . NEXT or GOSUB . . .
RETURN unless the lines repeat exactly. To make the repetition
complete, use a variable to represent the parts that are
different.
For example, suppose
your program contains these lines:
130 PRINT 29.3428+9.87627*SQR(5)
140 PRINT 29.3428+9.87627*SQR(7)
150 PRINT 29.3428+9.87627*SQR(9)
160 PRINT 29.3428+9.87627*SQR(11)
170 PRINT 29.3428+9.87627*SQR(13)
180 PRINT 29.3428+9.87627*SQR(15)
190 PRINT 29.3428+9.87627*SQR(17)
200 PRINT 29.3428+9.87627*SQR(19)
210 PRINT 29.3428+9.87627*SQR(21)
Each of those lines says PRINT 29.3428+9.87627*SQR(a number). The
number keeps changing, so call it X. Lines 130-210 can be
replaced by:
130 FOR X= 5 TO 21 STEP 2
140 PRINT 29.3428+9.87627*SQR(X)
150 NEXT
Here's a harder example
to fix:
130 PRINT 29.3428+9.87627*SQR(5)
140 PRINT 29.3428+9.87627*SQR(97.3)
150 PRINT 29.3428+9.87627*SQR(8.62)
160 PRINT 29.3428+9.87627*SQR(.4)
170 PRINT 29.3428+9.87627*SQR(200)
180 PRINT 29.3428+9.87627*SQR(12)
190 PRINT 29.3428+9.87627*SQR(591)
200 PRINT 29.3428+9.87627*SQR(.2)
210 PRINT 29.2428+9.87627*SQR(100076)
Again, let's use X. Those nine lines can be combined like this:
130 DATA 5,97.3,8.62,.4,200,12,591,.2,100076
140 FOR I = 1 TO 9
150 READ X
160 PRINT 29.3428+9.87627*SQR(X)
170 NEXT
This one's even tougher:
130 PRINT 29.3428+9.87627*SQR(A)
140 PRINT 29.3428+9.87627*SQR(B)
150 PRINT 29.3428+9.87627*SQR(C)
160 PRINT 29.3428+9.87627*SQR(D)
170 PRINT 29.3428+9.87627*SQR(E)
180 PRINT 29.3428+9.87627*SQR(F)
190 PRINT 29.3428+9.87627*SQR(G)
200 PRINT 29.3428+9.87627*SQR(H)
210 PRINT 29.3428+9.87627*SQR(I)
Let's assume A, B, C, D, E, F, G, H, and I have been computed
earlier in the program. The trick to shortening those lines is to
change the names of the variables. Throughout the program, say
X(1) instead of A, say X(2) instead of B, say X(3) instead of C,
etc. Say DIM X(9) at the beginning of your program. Then lines
130-210 can be written:
130 FOR I=1 TO 9
140 PRINT 29.3428+9.87627*SQR(X(I))
150 NEXT
MAKE IT EFFICIENT
Your program should be efficient. That means it should use as
little of the computer's time and memory as possible.
To use less of the computer's memory, make your DIMensions as
small as possible. Try writing the program without any arrays at
all; if that turns out to be terribly inconvenient, use the
smallest and fewest arrays possible.
To use less of the computer's time, avoid having the computer
do the same thing more than once.
These lines force the computer to compute SQR(8.2*N+7) three
times:
50 PRINT SQR(8.3*N+7)+2
60 PRINT SQR(8.3*N+7)/9.1
70 PRINT 5-SQR(8.3*N+7)
You should change them to:
49 K=SQR(8.3*N+7)
50 PRINT K+2
60 PRINT K/9.1
70 PRINT 5-K
These lines force the computer to compute X^9+2 a hundred
times:
50 FOR I = 1 TO 100
60 PRINT (X^9+2)/I
70 NEXT
You should change them to:
49 K=X^9+2
50 FOR I = 1 TO 100
60 PRINT K/I
70 NEXT
These lines force the computer to count to 100 twice:
50 S=0
60 FOR I = 1 TO 100
70 S=S+X(I)
80 NEXT
90 PRINT "THE SUM OF THE X'S IS";S
100 P=1
110 FOR I = 1 TO 100
120 P=P*X(I)
130 NEXT
140 PRINT "THE PRODUCT OF THE X'S IS";P
You should change them to:
50 S=0
51 P=1
60 FOR I = 1 TO 100
70 S=S+X(I)
71 P=P*X(I)
80 NEXT
90 PRINT "THE SUM OF THE X'S IS";S
140 PRINT "THE PRODUCT OF THE X'S IS";P
Here are more tricks for making your program run faster. . . .
Instead of exponents, use multiplication:
Slow Faster
50 Y=X^2 50 Y=X*X
Combine statements, to form a single
line:
Slow Faster
50 A=3 50 A=3: B=7
60 B=7
Warning: an IF statement cannot be combined with a later
statement.
Cannot be combined
50 IF I<1 THEN GO TO 200
60 B=7
If a number contains a decimal point
and is in a loop, turn the number into a variable:
Slow Faster
49 C=3.1
50 FOR I = 1 TO 900 50 FOR I = 1 TO 900
60 S=S+3.1/I 60 S=S+C/I
70 NEXT 70 NEXT
Omit the variable after NEXT (unless
the FOR...NEXT loop contains another FOR...NEXT loop):
Slow Faster
50 NEXT I 50 NEXT
If your program doesn't involve
decimals or large numbers, put this statement at the beginning of
your program:
1 DEFINT A-Z
If your program involves just a few decimals or large numbers,
begin your program by saying DEFINT A-Z, and put an exclamation
point after every variable that stands for a real number.
Alphabetizing
Suppose you want the computer to
alphabetize a list of names. What's the best strategy?
Imagine trying to alphabetize the
list yourself ___ each name is written on a file card, and you
have to put the deck of cards in alphabetical order.
One strategy would be to compare the
second card with the first, and swap them if necessary; then look
at the third card, and swap if necessary; and so on to the end of
the deck. A different strategy would be to put all the A's in one
pile, all the B's in another, etc., and then sort each pile.
Which strategy is better? If the
file has ten cards or less, the swap method is faster; if the
file is very long, the 26-pile method is faster but requires
space to lay out 26 piles.
Which method would make a more
efficient program? That depends on how long the file is and
whether your computer lacks fast parts or large memory.
Prime numbers
An integer is called composite if
it's the product of two other integers. 35 is composite, because
it's 5*7; 9 is composite, because it's 3*3; 12 is composite,
because it's 2*6; 13 is not composite, and is therefore called
prime. This program tells whether a number is prime or composite:
10 INPUT "WHAT'S YOUR FAVORITE POSITIVE INTEGER";N
20 FOR I = 1 TO N-1
30 FOR J = 1 TO N-1
40 IF N=I*J THEN PRINT N;"IS";I;"TIMES";J;"AND
COMPOSITE": END
50 NEXT
60 NEXT
70 PRINT N;"IS PRIME"
Line 10 waits for you to type a number N. Line 40 checks whether
N is the product of two other integers; if it is, the computer
says N is composite.
How efficient is that program? Since it contains no arrays, it
doesn't require much space in the memory. But if N turns out to
be prime, line 40 is encountered once for every I and once for
every J; altogether it's encountered (N-1)2 times. If N is a
large number, around a million, (N-1)2 is around a trillion. To
do line 40 a trillion times will take a typical microcomputer
many years. In fact, if you say that your favorite number is
999983 (which is close to a million), the typical microcomputer
will take about 200 years before it comes to the conclusion that
your number is prime! By the time the program finishes running,
you'll be dead and so will your children! The program's very
inefficient.
Some small improvements are possible; for example, I and J can
start at 2 instead of 1. But so long as you have a loop inside a
loop, the time will remain very large.
The following strategy requires just one loop: divide N by
every integer less than it, to see whether the quotient is ever
an integer. Here's the program:
10 INPUT "WHAT'S YOUR FAVORITE POSITIVE NUMBER";N
20 FOR I = 2 TO N-1
40 Q=N/I: IF Q=INT(Q) THEN PRINT N;"IS";I;"TIMES";Q;"AND
COMPOSITE":END
60 NEXT
70 PRINT N;"IS PRIME"
Line 40 consists of two parts. The first part says to divide N by
an integer (I); the quotient's called Q. The second part says
that if Q is an integer, N is composite.
How efficient is our new program? If N turns out to be prime,
line 40 is encountered once for every I; altogether it's
encountered N-2 times. That's less than in the previous program,
where it was encountered (N-1)2 times. If N is about a million,
our new program is nearly a million times faster than the
previous one! To determine whether 999983 is prime, the new
program takes a typical microcomputer about 3 hours instead of
200 years.
We can improve the program even further. If an N can't be
divided by 2, it can't be divided by any even number; so after
checking divisibility by 2, we have to check divisibility by just
3, 5, 7, . . . , N-2. Let's put that short-cut into our program,
and also say that every N less than 4 is prime:
10 INPUT "WHAT'S YOUR FAVORITE NUMBER";N
11 IF N<4 THEN PRINT N;"IS PRIME":END
12 Q=N/2: IF Q=INT(Q) THEN PRINT N;"IS 2 TIMES";Q;"AND
COMPOSITE": END
20 FOR I = 3 TO N-2 STEP 2
40 Q=N/I: IF Q=INT(Q) THEN PRINT N;"IS";I;"TIMES";Q;"AND
COMPOSITE": END
60 NEXT
70 PRINT N;"IS PRIME"
Line 12 checks divisibility by 2; lines 20-60 check divisibility
by 3, 5, 7, . . . , N-2. If N is prime, line 40 is encountered
N/2 - 2 times, which is about half as often as in the previous
program; so our new program takes about half as long to run. On a
typical microcomputer, it takes about 1½ hours to handle 999983.
Our goal was to find a pair of integers whose product is N. If
there is such a pair of integers, the smaller one will be no more
than the square root of N, so we can restrict our hunt to the
integers not exceeding the square root of N:
10 INPUT "WHAT'S YOUR FAVORITE NUMBER";N
11 IF N<4 THEN PRINT N;"IS PRIME":END
12 Q=N/2: IF Q=INT(Q) THEN PRINT N;"IS 2 TIMES";Q;"AND
COMPOSITE": END
20 FOR I = 3 TO SQR(N)*1.00001 STEP 2
40 Q=N/I: IF Q=INT(Q) THEN PRINT N;"IS";I;"TIMES";Q;"AND
COMPOSITE": END
60 NEXT
70 PRINT N;"IS PRIME"
The ``1.00001'' is to give a margin of safety, in case the
computer rounds SQR(N) a bit down. If N is near a million, line
40 is encountered about 500 times, which is much less than the
500,000 times encountered in the previous program and the
1,000,000,000,000 times in the original. This program lets the
typical microcomputer handle 999983 in about 6 seconds. That's
much quicker than the earlier versions, which required 1½ hours,
or 3 hours, or 200 years!
Moral: a few small changes in a program can make the computer
take 6 seconds instead of 200 years.
The frightening thing about this example is that the first
version we had was so terrible, but the only way to significantly
improve it was to take a totally fresh approach. To be a
successful programmer, you must always keep your mind open, and
hunt for fresh ideas.
DON'T BE SILLY
After you've written a program, skim through it to see whether
any of its lines are silly. Eliminate the silly lines, so that
your program becomes briefer, simpler, and more pleasant.
In the following examples, I assume your program is numbered
10, 20, 30, 40, . . .
Don't tell the computer to GO TO the next line
For example, don't say:
30 GO TO 40
Omit it. The computer will go to line 40 anyway.
Here's another example of a GO TO that goes to the next line:
30 IF X<7 THEN GO TO 40
Omit it. The computer will go to line 40 anyway.
Here's another example of a GO TO that goes to the next line:
30 IF X<7 THEN PRINT "WOW" ELSE GO TO 40
Omit the ``ELSE GO TO 40''; just say:
30 IF X<7 THEN PRINT "WOW"
Don't write an IF that skips over just one line
For example, don't write:
30 IF X<7 THEN GO TO 50
40 PRINT "WOW"
That line 30 is an IF that skips over just line 40. It's silly!
Combine lines 30 and 40 into a single line:
30 IF X>=7 THEN PRINT "WOW"
Don't write an IF followed by its opposite
For example, don't write:
30 IF X<7 THEN PRINT "GEE"
40 IF X>=7 THEN PRINT "WOW"
Combine them into a single line:
30 IF X<7 THEN PRINT "GEE" ELSE PRINT "WOW"
(That combination works only on computers that understand the
word ELSE.)
Here's another example of an IF followed by its opposite:
30 IF X<7 THEN GO TO 100
40 IF X>=7 THEN PRINT "WOW"
Remove the IF from line 40:
30 IF X<7 THEN GO TO 100
40 PRINT "WOW"
The new version does the same thing as the original, because the
computer reaches the new 40 only if X is not less than 7.
Here's
another IF followed by its opposite:
30 IF X<7 THEN GO TO 50
40 IF X>=7 THEN PRINT "WOW"
Applying the same technique as before, remove the IF from line
40:
30 IF X<7 THEN GO TO 50
40 PRINT "WOW"
But also notice that line 30 is an IF that skips over just one
line; we've uncovered another piece of silliness! Applying more
cosmetics, we get down to a single line:
30 IF X>=7 THEN PRINT "WOW"
Here's
another IF followed by its opposites:
30 IF X<7 THEN GO TO 100
40 IF X=7 THEN GO TO 200
50 IF X>7 THEN PRINT "WOW"
Remove the last IF:
30 IF X<7 THEN GO TO 100
40 IF X=7 THEN GO TO 200
50 PRINT "WOW"
AVOID ROUND-OFF ERRORS
The computer cannot handle decimals accurately. If you say
X=.1, the computer can't set X equal to .1 exactly; instead, it
will set X equal to a number very, very close to .1. The reason
for the slight inaccuracy is that the computer thinks in
``binary'', not decimals; and .1 cannot be expressed in binary
exactly.
Usually you won't see the slight inaccuracy: when you ask the
computer to PRINT a number, the computer prints it rounded to six
significant figures, and the inaccuracy is so small it doesn't
show up in the rounded result. But there are three situations in
which the inaccuracy can be noticed:
1. Telling the computer to do A-B, where A is almost equal to
B, and the first several digits of A are the same as the first
several digits of B. For example, if you ask a typical
microcomputer to print 8.001-8, the computer will not print .001;
instead it will print .000999451. The same thing happens if you
do 8.001+(-8).
If you ask the typical microcomputer to print 987654.1-987654,
it will print .125 instead of .1. The error can get magnified: if
you ask the computer to multiply 987654.1-987654 by 1000, it will
print .125*1000, which is 125, instead of .1*1000, which is 100.
If you ask it to find the reciprocal of 987654.1-987654, it will
print 1/.125, which is 8, instead of 1/.1, which is 10.
Those are the errors produced by a typical microcomputer. The
errors produced by your computer might be slightly more or less.
But even if your computer is a maxi that costs $10,000,000, it
makes those same kinds of errors.
2. Saying ``FOR X = A TO B STEP C'', where C is a decimal and
the loop will be done many times. For example:
10 FOR X = 1 TO 2 STEP .1
20 PRINT X
30 NEXT
Theoretically, the computer should print 1, 1.1, 1.2, 1.3, 1.4,
1.5, 1.6, 1.7, 1.8, 1.9, and 2. But that's not what actually
happens. In line 10, the computer can't handle the decimal .1
accurately. The last few numbers the typical microcomputer thinks
of are:
slightly more than 1.7
slightly more than 1.8
slightly more than 1.9
The computer does not think of the next number, slightly more
than 2.0, because line 10 says not to go past 2. In line 20, the
word PRINT makes the computer print the numbers rounded to six
significant digits, so it prints:
1
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
It does not print 2.
If you want to compute 1 + 1.1 + 1.2 + 1.3 + 1.4 + 1.5 + 1.6 +
1.7 + 1.8 + 1.9 + 2, you might be tempted to write this program:
5 S=0
10 FOR X = 1 TO 2 STEP .1
20 S=S+X
30 NEXT
40 PRINT S
The computer will print a reasonable-looking answer: 14.5. But
that ``answer'' is wrong, because the last number it added was
slightly more than 1.9; it never added 2. The correct answer is
16.5.
One remedy is to change
line 10 to this:
10 FOR X = 1 TO 2.05 STEP .1
The .05 after the 2 allows for the margin of error. The general
strategy is to change ___
10 FOR X = A TO B STEP C
to this:
10 FOR X = A TO B+C/2 STEP C
An alternative remedy is
to replace ___
10 FOR X = 1 TO 2 STEP .1
by this pair of lines:
10 FOR I = 10 TO 20
11 X= I/10
As I goes from 10 to 20, X will go from 1 to 2 in steps of .1.
This remedy is the most accurate of all, since it eliminates
decimals from line 10. But the division in line 11 makes the
program very slow.
3. Asking the computer
whether two numbers X and Y are equal. It's unwise to ask whether
X is exactly equal to Y, since both X and Y have probably been
affected by some slight error. Instead, ask the computer whether
the difference between X and Y is much tinier than Y:
Bad Good
IF X=Y THEN IF
ABS(X-Y)<=.000001*ABS(Y) THEN
The .000001 is requesting that the first six significant digits
of X be the same as the first six significant digits of Y (except
that the sixth significant digit might be off by one).
Why binary?
From those discussions,
you might think computers should be made differently, and that
they should use the decimal system instead of binary. There are
two counterarguments.
First, binary arithmetic
is faster.
Second, even if
computers were using the decimal system, inaccuracy would still
occur. To store the fraction 2/3 accurately by using the decimal
system, the computer would have to store a decimal point followed
by infinitely many 6's. That would require an infinite amount of
space in memory, which is impossible (unless you know how to
build an infinitely large computer?) So even in the decimal
system, some fractions must be approximated instead of handled
exactly.
Begin with the tiny
According to
mathematicians, addition is supposed to obey these laws:
A+0 is exactly the same as A
A+B is exactly the same as B+A
A+-A is exactly the same as 0
(A+B)+C is exactly the same as A+(B+C)
On the computer, the
first three laws hold, but the last does not. If A is a decimal
tinier than C, the computer does (A+B)+C more accurately than
A+(B+C). So to add a list of numbers accurately, begin by adding
together the tiniest decimals in the list.
TEST YOUR PROGRAM
When you've written a program, test it: type RUN and see
whether it works.
If the computer does not gripe, your tendency will be to say
``Whoopee!'' Don't cheer too loudly. The answers the computer is
printing may be wrong. Even if its answers look reasonable, don't
assume they're right: the computer's errors can be very subtle.
Check some of its answers by doing them with a pencil.
Even if the answers the computer prints are correct, don't
cheer. Maybe you were just lucky. Type different input, and see
whether your program still works. Chances are, there's something
you can input that will make your program go crazy or print a
wrong answer. Your mission: to find input that will reveal the
existence of a bug.
Try six kinds of input. . . .
Try simple input
Type in simple integers, like 2 and 10, so the computation is
simple, and you can check the computer's answers easily.
Try input that increases
See how the computer's answer changes when the input changes
from 2 to 1000.
Does the change in the computer's answer look reasonable? Does
the computer's answer go up when it should go up, and down when
it should go down? . . . and by a reasonable amount?
Try input testing each IF
For a program that says ___
30 IF X<7 THEN GO TO 100
input an X less than 7 (to see whether line 100 works), then an X
greater than 7 (to see whether line 40 works), then an X equal to
7 (to see whether you really want ``<'' instead of ``<=''), then
an X very close to 7, to check round-off error.
For a program that says ___
30 IF A^2+B<C THEN GO TO 100
input an A, B, and C that make A^2+B less than C. Then try inputs
that make A^2+B very close to C.
Try extreme input
What happens if you input:
a huge number, like 45392000000 or 1E35?
a tiny number, like .00000003954 or 1E-35?
a trivial number, like 0 or 1?
a typical number, like 45.13?
a negative number, like -52?
Find out.
If the input is supposed to be a
string, what happens if you input AAAAA or ZZZZZ? If there are
supposed to be two inputs, what happens if you input the same
thing for each?
Try input making some lines act strange
If your program contains division,
try input that will make the divisor be zero or a tiny decimal
close to zero. If your program contains the square root of a
quantity, try input that will make the quantity be negative. If
your program says ``FOR I=A TO B'', try input that will make B be
less than A, then equal to A. If your program mentions X(I), try
input that will make I be zero or negative or greater than the
DIM.
Try input that causes round-off
error: for a program that says ``A-B'' or says ``IF A=B THEN'',
try input that will make A almost equal B.
Try garbage
Many people hate computers because
they often print wrong answers. A computer can print a wrong
answer because its machinery is broken, or because a program has
a bug. But the main reason why computers print wrong answers is
that the input is incorrect. Incorrect input is called garbage.
It has several causes. . . .
The user's finger slips Instead of
400, he inputs 4000. Instead of 27, he inputs 72. Trying to type
.753, he leaves out the decimal point.
The user got wrong information He
tries to input the temperature, but his thermometer is leaking.
He tries to input the results of a questionnaire, but everybody
who filled out his questionnaires lied.
The instructions aren't clear The
program asks HOW FAR DID THE BALL FALL, and the user doesn't know
whether to type the distance in feet or in meters.
Is time to be given in seconds or
minutes? Are angles to be measured in degrees or radians?
If the program asks WHAT IS YOUR
NAME, should the user type JOE SMITH or ``SMITH,JOE'' or just
JOE?
Can the user input Y instead of YES?
Maybe the user isn't clear about
whether to insert commas, quotation marks, and periods. If
several items are to be typed, should they be typed on the same
line or on separate lines? If your program asks HOW MANY BROTHERS
AND SISTERS DO YOU HAVE, and the user has 2 brothers and 3
sisters, should he type 5 or ``2,3'' or ``2 BROTHERS AND 3
SISTERS''?
For a quiz that asks WHO WAS THE
FIRST U.S. PRESIDENT, what if the user answers GEORGE WASHINGTON
or simply WASHINGTON or G. WASHINGTON or GENERAL GEORGE
WASHINGTON or PRESIDENT WASHINGTON or MARTHA'S HUSBAND? Make the
instructions clearer:
WHO WAS THE FIRST U.S. PRESIDENT (GIVE JUST HIS LAST NAME)?
The user is trying to be funny or
sabotage the computer Instead of inputting his name, he types an
obscene comment. When asked how many brothers and sisters he has,
he says 275.
Responsibility It's your
responsibility as a programmer to make sure that the directions
for using your program are clear, and that the program rejects
ridiculous input.
For example, if your program is
supposed to print weekly paychecks, it should refuse to print
checks for more than $10000. Your program should contain these
lines:
20 INPUT "HOW MUCH MONEY DID THE EMPLOYEE EARN";E
30 IF E>10000 THEN PRINT E;"IS QUITE A BIG PAYCHECK! I DON'T
BELIEVE YOU.": PRIN T "PLEASE RETYPE YOUR REQUEST.": GO TO 20
Line 30 is called an error trap (or an error-handling routine).
Your program should contain several, to prevent printing checks
that are too small (2¢?) or negative or otherwise ridiculous
($200.73145?)
To see how your program reacts to
input that's either garbage or unusual, ask the person sitting
next to you to run your program. That person might input
something you never thought of.
DOCUMENT IT
Write an explanation that helps other people understand your
program. An explanation is called documentation; when you write
an explanation, you're documenting the program.
You can write the documentation on a separate sheet of paper
(to be put in the computer center's library), or you can make the
computer print the documentation when the user types RUN or LIST.
A popular device is to begin the RUN by making the computer ask
the user:
DO YOU NEED INSTRUCTIONS?
You need two kinds of documentation: how to use the program,
and how the program was written.
How to use the program
Your explanation of how to use the program should include:
the program's name
how to get the program from the disk
the program's purpose
a list of other programs that must be combined with this program,
to make a workable combination
the correct way to type the input and data (show an example)
the correct way to interpret the output
the program's limitations (input it can't handle, a list of error
messages that might be printed, round-off error)
a list of bugs you haven't fixed yet
How the program was written
An explanation of how you wrote the program will help other
programmers borrow your ideas, and help them expand your program
to meet new situations. It should include:
your name
the date you finished it
the computer you wrote it for
the language you wrote it in (probably BASIC)
the name of the method you used (``solves quadratic equations by
using the quadratic formula'')
the name of the book or magazine where you found the method
the name of any program you borrowed ideas from
an informal explanation of how program works (``It loops until
A>B, then computes the weather forecast.'')
the purpose of each module
the meaning of each variable
the meaning of reaching a line (if the program says IF X<60 THEN
GO TO 1000, say ``Reaching line 1000 means the student
flunked.'')